package cn.edu.nuaa.aadl2.generatorC.template

import org.osate.aadl2.ThreadSubcomponent
import cn.edu.nuaa.aadl2.generatorC.utils.Tools
import static extension cn.edu.nuaa.aadl2.generatorC.template.AnnexTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.utils.StringUtils.*
import static extension cn.edu.nuaa.aadl2.generatorC.utils.PropertyParser.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.SubprogramTemplate.*
import static extension cn.edu.nuaa.aadl2.generatorC.template.FeatureTemplate.*
import org.osate.aadl2.ThreadType
import org.osate.aadl2.ThreadImplementation
import org.osate.aadl2.SubprogramCall
import org.osate.aadl2.SubprogramClassifier
import org.osate.aadl2.ThreadClassifier
import org.osate.aadl2.Subcomponent
import org.osate.aadl2.Feature
import java.util.List
import org.osate.aadl2.AnnexSubclause
import org.osate.ba.aadlba.impl.BehaviorAnnexImpl
import org.osate.aadl2.DefaultAnnexSubclause
import org.osate.aadl2.impl.DefaultAnnexSubclauseImpl
import org.osate.aadl2.SubprogramCallSequence
import java.util.logging.FileHandler
import cn.edu.nuaa.aadl2.generatorC.utils.FileHelper

class ThreadTemplate {
	
	
	def static createThread(ThreadSubcomponent subcomponent,String process_folder)'''
		«Tools.createFile(process_folder,subcomponent.classifier.name.convert+"_thread.h",subcomponent.head.toString)»
		«Tools.createFile(process_folder,subcomponent.classifier.name.convert+"_thread.c",subcomponent.template(process_folder).toString)»
		
		
		«FileHelper.createFile(Template.aimPath+"/"+process_folder,subcomponent.classifier.name.convert+"_thread.h",subcomponent.head.toString)»
		«FileHelper.createFile(Template.aimPath+"/"+process_folder,subcomponent.classifier.name.convert+"_thread.c",subcomponent.template(process_folder).toString)»
	
	'''
	
	
	/*
	 * 处理进程实现下的线程子组件
	 * @param threadSubcomponents 线程子组件列表
	 */
	def static genProcessThreadSubcomponent(List<ThreadSubcomponent> threadSubcomponents,String process_folder)'''
		«FOR threadSubcomponent : threadSubcomponents»
			«threadSubcomponent.head»
			«threadSubcomponent.template(process_folder)»
		«ENDFOR»
	'''
	
	def static head(ThreadSubcomponent subcomponent){
		var thread=subcomponent.classifier
		switch thread{
			ThreadType : '''
				/*Thread Type head file*/
				«Template.head»
			'''
			ThreadImplementation : '''
				/*Thread head c file*/
				«Template.head»
				

				#include "«subcomponent.containingClassifier.name.convert»_process.h"	
				/***********************************
				* deal with thread feature!!!!	start!
				************************************/	
				«FOR feature : thread.allFeatures»
					«feature.template»
				«ENDFOR»				
				/***********************************
				* deal with thread feature!!!!	end!
				************************************/	
			'''
		}
	}
	
	def static template(ThreadSubcomponent subcomponent,String process_folder){
		var thread=subcomponent.classifier
		switch thread{
			ThreadClassifier:'''
			«thread.template(process_folder)»
			'''
		}
	}
	
		
	def static template(ThreadClassifier thread,String process_folder){
		switch thread{
			ThreadType : '''
				/*Thread Type c file*/
				«Template.head»
				#include "«thread.name.convert+"_thread.h"»"	
					/*features in thread*/
					«IF thread.getAllFeatures!=null»
						«thread.getAllFeatures.asVariables»
					«ENDIF»
«««					«IF thread.dispatchProtocol.equalsIgnoreCase("Periodic")»
«««						while(1)
«««						{
«««							
«««						}
«««					«ENDIF»
			'''
			ThreadImplementation : '''
				/*Thread Implementation c file*/
				«Template.head»
				#include "«thread.name.convert+"_thread.h"»"					
				«IF thread.getSubprogramCalls!=null»
					«FOR SubprogramCall sc : thread.getSubprogramCalls»
						«IF sc.calledSubprogram!=null»
							«sc.calledSubprogram.create(process_folder)»
							«IF sc.calledSubprogram instanceof SubprogramClassifier»
								«sc.calledSubprogram.include»
							«ENDIF»
						«ENDIF»
					«ENDFOR»
				«ENDIF»				
				void thread_«thread.name.convert»()
				{
«««					/*---features in thread---*/
«««					«IF thread.type.getAllFeatures!=null»
«««						«thread.type.getAllFeatures.asVariables»
«««					«ENDIF»
«««					/*---features in thread---*/
				
				«IF thread.ownedAnnexSubclauses.size <= 0»
					/*---subprogram in thread with different type---*/
					«IF thread.dispatchProtocol.equalsIgnoreCase("Periodic")»
						while(1)
						{
							
							«IF thread.getSubprogramCalls!=null»
								«FOR SubprogramCall sc : thread.getSubprogramCalls»
									«IF sc.calledSubprogram!=null»
										«sc.calledSubprogram.inThread»
									«ENDIF»
								«ENDFOR»
							«ENDIF»	
							
						}
					«ENDIF»
					«IF thread.dispatchProtocol.equalsIgnoreCase("Sporadic")»						
						«IF thread.getSubprogramCalls!=null»
							«FOR SubprogramCall sc : thread.getSubprogramCalls»
								«IF sc.calledSubprogram!=null»
									«sc.calledSubprogram.inThread»
								«ENDIF»
							«ENDFOR»
						«ENDIF»	
					«ENDIF»
					«IF thread.dispatchProtocol.equalsIgnoreCase("Aperiodic")»
						«IF thread.getSubprogramCalls!=null»
							«FOR SubprogramCall sc : thread.getSubprogramCalls»
								«IF sc.calledSubprogram!=null»
									«sc.calledSubprogram.inThread»
								«ENDIF»
							«ENDFOR»
						«ENDIF»
					«ENDIF»
					«IF thread.dispatchProtocol.equalsIgnoreCase("Timed")»
						«IF thread.getSubprogramCalls!=null»
							«FOR SubprogramCall sc : thread.getSubprogramCalls»
								«IF sc.calledSubprogram!=null»
									«sc.calledSubprogram.inThread»
								«ENDIF»
							«ENDFOR»
						«ENDIF»
					«ENDIF»
					«IF thread.dispatchProtocol.equalsIgnoreCase("Hybrid")»
						«IF thread.getSubprogramCalls!=null»
							«FOR SubprogramCall sc : thread.getSubprogramCalls»
								«IF sc.calledSubprogram!=null»
									«sc.calledSubprogram.inThread»
								«ENDIF»
							«ENDFOR»
						«ENDIF»
					«ENDIF»
					«IF thread.dispatchProtocol.equalsIgnoreCase("Background")»
						«IF thread.getSubprogramCalls!=null»
							«FOR SubprogramCall sc : thread.getSubprogramCalls»
								«IF sc.calledSubprogram!=null»
									«sc.calledSubprogram.inThread»
								«ENDIF»
							«ENDFOR»
						«ENDIF»
					«ENDIF»
					/*---subprogram in thread with different type---*/
				«ELSEIF thread.ownedAnnexSubclauses.size > 0»
						«thread.name.convertNo2Low»_BehaviorAnnex();
				«ENDIF»
					
				}

				«IF thread.ownedAnnexSubclauses.size > 0»
					«FOR AnnexSubclause annexSubclause : thread.ownedAnnexSubclauses»
						«AnnexSwitch(thread.name.convertNo2Low,annexSubclause as DefaultAnnexSubclauseImpl,"",false).toString»
					«ENDFOR»
				«ENDIF»				
				
			'''
		}
	}
}